<template>
  <div class="container mx-auto px-4 py-8 max-w-6xl">
    <!-- 加载状态提示 -->
    <div v-if="isLoading" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
      <div class="bg-white rounded-lg p-6 flex items-center space-x-4">
        <div class="animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-primary"></div>
        <span class="text-gray-700">加载中，请稍候...</span>
      </div>
    </div>

    <!-- 顶部导航 -->
    <nav class="bg-white rounded-xl shadow-sm p=4 mb-4 flex items-center justify-between transition-all duration-300 hover:shadow-md">
      <!-- 左侧标题区域 -->
      <div class="flex items-center space-x-3">
        <h1 class="text-xl pl-3  pr-2 font-bold text-gray-800">桩基详情</h1>
      </div>

      <!-- 右侧搜索区域 -->
      <div class="flex items-center space-x-4">
        <div class="relative w-64 lg:w-80">
          <input
              v-model="searchPileNumber"
              type="search"
              placeholder="请输入桩号..."
              class="w-full  p-2 pl-8 rounded-full border border-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 text-sm"
              @keyup.enter="searchPile"
              autofocus
          />
          <i class="fa fa-search absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
          <button
              @click="searchPile"
              class="absolute right-1 top-1 bottom-1 px-6 bg-gradient-to-r from-blue-500 to-indigo-600 text-white rounded-full hover:shadow-lg hover:from-blue-600 hover:to-indigo-700 transition-all duration-300 flex items-center justify-center text-sm font-medium"
          >
            <i class="fa fa-search mr-1.5"></i> 搜索
          </button>
        </div>

      </div>
    </nav>
    <!-- 主内容区 -->
    <main class="space-y-8">
      <!-- 桩基基本信息卡片 -->
      <div class="bg-white rounded-xl p-6 card-shadow">
        <div class="flex flex-col md:flex-row md:items-center justify-between mb-6">
          <div>
            <div class="flex items-center space-x-3">
              <h3 class="text-lg font-semibold text-neutral">桩号: {{ pile.pileNumber }}#</h3>
              <span class="bg-green-100 text-green-700 px-3 py-1 rounded-full text-sm font-medium">
                <i class="fa fa-check-circle mr-1"></i>{{ formatDateTime (pile.pouringTime)+'完成' || '未完成施工'}}
              </span>
            </div>
<!--            <h2 class="text-2xl font-bold mt-2 text-neutral">桩基 #{{ pile.id }} 详情</h2>-->
            <p class="text-gray-500 mt-1">里程: K0+{{ pile.mileage }} 偏距: {{pile.offset<0 ? '左'+pile.offset*-1 : '右'+pile.offset}}m </p>
            <p class="text-gray-500 mt-1">坐标: ({{ pile.coordinateX }}, {{ pile.coordinateY }})</p>
          </div>
          <div class="mt-4 md:mt-0 flex space-x-3">
<!--            <button class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="editPile">
              <i class="fa fa-edit"></i>
              <span>编辑</span>
            </button>-->

            <button
                v-if="!isOver"
                class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded"
            >
              工序未完成不能导出数据
            </button>
            <button
                v-else-if="!excelFiles.length"
                @click="exportExcel"
                class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded"
            >
              导出质检及收方资料
            </button>
            <div v-else>
            <button  class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="exportPile">
              <i class="fa fa-download"></i>
              <span>
               <a  :href="FILE_SERVER_URL+pileNumber+'/'+pileNumber+'号桩基质检及收方资料.xlsx'">{{pileNumber}}号桩基质检及收方资料.xlsx</a>
              </span>

            </button>
            <button  class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="exportPile">
              <i class="fa fa-download"></i>
              <span>
                <a  :href="FILE_SERVER_URL+pileNumber+'/'+pileNumber+'号桩基质检资料筑业版.xlsx'">{{pileNumber}}号桩基质检资料筑业版.xlsx</a>
              </span>
            </button>
            </div>

          </div>
        </div>

        <!-- 桩基参数卡片 -->
        <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
          <div class="stat-card">
            <div class="flex justify-between items-start">
              <div>
                <p class="text-gray-500 text-sm">桩长</p>
                <h3 class="text-2xl font-bold mt-1">{{ pile.pileLength }}<span class="text-sm font-normal ml-1">m</span></h3>
              </div>
              <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-primary">
                <i class="fa fa-arrows-v " ></i>
              </div>
            </div>
            <div class="mt-4 pt-4 border-t border-gray-100">
              <div class="flex justify-between">
                <div>
                  <p class="text-xs text-gray-500">桩底高程</p>
                  <p class="text-sm font-medium">{{ pile.pileBottomElevation }}m</p>
                </div>
                <div>
                  <p class="text-xs text-gray-500">桩顶高程</p>
                  <p class="text-sm font-medium">{{ pile.pileTopElevation }}m</p>
                </div>
              </div>
            </div>
          </div>

          <div class="stat-card">
            <div class="flex justify-between items-start">
              <div>
                <p class="text-gray-500 text-sm">桩径</p>
                <h3 class="text-2xl font-bold mt-1">{{ pile.pileDiameter }}<span class="text-sm font-normal ml-1">m</span></h3>
              </div>
              <div class="w-10 h-10 rounded-full bg-green-100 flex items-center justify-center text-secondary">
                <i class="fa fa-circle"></i>
              </div>
            </div>
            <div class="mt-4 pt-4 border-t border-gray-100">
              <div class="flex justify-between">
                <div>
                  <p class="text-xs text-gray-500">钢筋笼长度</p>
                  <p class="text-sm font-medium">{{ pile.steelCageLength }}m</p>
                </div>
                <div>
                  <p class="text-xs text-gray-500">超灌长度</p>
                  <p class="text-sm font-medium">{{ pile.overPouringLength }}m</p>
                </div>
              </div>
            </div>
          </div>

          <div class="stat-card">
            <div class="flex justify-between items-start">
              <div>
                <p class="text-gray-500 text-sm">施工耗时</p>
                <h3 class="text-2xl font-bold mt-1">{{ constructionHours }}<span class="text-sm font-normal ml-1">小时</span></h3>
              </div>
              <div class="w-10 h-10 rounded-full bg-orange-100 flex items-center justify-center text-accent">
                <i class="fa fa-clock"></i>
              </div>
            </div>
            <div class="mt-4 pt-4 border-t border-gray-100">
              <div class="flex justify-between">
                <div>
                  <p class="text-xs text-gray-500">开钻时间</p>
                  <p class="text-sm font-medium"><span @dblclick="startEditing('holeOpeningTime',pile.holeOpeningTime,true)">{{ formatDateTime(pile.holeOpeningTime) }}</span></p>
                </div>
                <div>
                  <p class="text-xs text-gray-500">浇筑时间</p>
                  <p class="text-sm font-medium"><span @dblclick="startEditing('pouringTime',pile.pouringTime,true)">{{ formatDateTime(pile.pouringTime) }}</span></p>
                </div>
              </div>
            </div>
          </div>
        </div>


        <!-- 施工图片和视频区域 -->
        <div class="bg-white rounded-lg p-4 mb-8">
          <div class="flex justify-between items-center mb-6">
            <h3 class="text-lg font-semibold text-neutral">施工影像资料</h3>
<!--            <button class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="openUploadModal">
              <i class="fa fa-upload mr-1"><span>上传影像</span></i>

            </button>-->
            <button @click="openUploadModal" class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" >
              <span>上传影像</span>
            </button>
          </div>

          <!-- 上传模态框 -->
          <div v-if="isUploadModalOpen" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
            <div class="bg-white rounded-lg p-6 max-w-md w-full mx-4 transform transition-all">
              <div class="flex justify-between items-center mb-4">
                <h3 class="text-lg font-semibold">上传影像资料</h3>
                <button @click="closeUploadModal" class="text-gray-400 hover:text-gray-600">
                  <i class="fa fa-times"></i>
                </button>
              </div>
              <div class="mb-4">
                <label class="block text-sm font-medium text-gray-700 mb-2">选择操作阶段</label>
                <select v-model="selectedOperation" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary">

                  <option value="现场收方单">现场收方单</option>
                  <option value="桩基放样">桩基放样</option>
                  <option value="复核时间">复核时间</option>

                  <option value="开孔时间">开孔时间</option>
                  <option value="下钢筋笼时间">下钢筋笼时间</option>
                  <option value="浇筑时间">浇筑时间</option>

                  <option value="桩孔验收">桩孔验收</option>
                  <option value="钢筋笼验收">钢筋笼验收</option>
                  <option value="砼磅单">砼磅单</option>


                </select>
              </div>
              <div class="mb-4">
                <label class="block text-sm font-medium text-gray-700 mb-2">上传文件</label>
                <div class="relative border-2 border-dashed border-gray-300 rounded-lg p-8 text-center hover:border-primary transition-colors cursor-pointer" @click="fileInput.click">
                  <input type="file" ref="fileInput" class="hidden" @change="handleFileUpload" accept="image/*,video/*">
                  <i class="fa fa-cloud-upload text-3xl text-gray-400 mb-2"></i>
                  <p class="text-gray-500">点击或拖拽文件到此处上传</p>
                  <p class="text-xs text-gray-400 mt-1">支持 JPG, PNG, MP4 格式</p>
                  <div v-if="selectedFile" class="mt-3 bg-gray-50 p-2 rounded text-sm">
                    <i class="fa fa-file mr-1"></i> {{ selectedFile.name }} ({{ getFileSize(selectedFile.size) }})
                  </div>
                </div>
              </div>
              <div class="flex justify-end space-x-3">
                <button @click="closeUploadModal" class="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
                  取消
                </button>
                <button @click="confirmUpload" class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-red bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary" :disabled="!selectedFile">
                  <i class="fa fa-upload mr-1"></i>确认上传
                </button>
              </div>
            </div>
          </div>

          <!-- 上传进度条 -->
          <div v-if="uploadProgress > 0 && uploadProgress < 100" class="fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-white rounded-lg p-4 shadow-lg flex items-center space-x-4 w-80">
            <div class="w-full">
              <div class="text-sm font-medium text-gray-700 mb-1">上传中...</div>
              <div class="w-full bg-gray-200 rounded-full h-2.5">
                <div class="bg-primary h-2.5 rounded-full" :style="{ width: `${uploadProgress}%` }"></div>
              </div>
              <div class="text-xs text-gray-500 mt-1">
                {{ uploadProgress }}% - {{ selectedFile.name.substring(0, 20) }}{{ selectedFile.name.length > 20 ? '...' : '' }}
              </div>
            </div>
          </div>

          <!-- 图片和视频网格 -->
          <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
            <!-- 占位提示 -->
            <div v-if="!constructionMedia.length" class="col-span-full bg-gray-50 rounded-lg p-8 text-center">
              <i class="fa fa-image text-4xl text-gray-300 mb-4"></i>
              <p class="text-gray-500">暂无施工影像资料</p>
              <p class="text-sm text-gray-400 mt-2">点击上方"上传影像"按钮添加施工过程中的照片或视频</p>
            </div>

            <!-- 图片和视频项 -->
<!--            <div v-for="(media, index) in constructionMedia" :key="index" class="group">
              <div class="relative rounded-lg overflow-hidden shadow-md h-64">
                <div v-if="isImage(media.fileName)" class="absolute inset-0 bg-center bg-contain bg-no-repeat" :style="{ backgroundImage: `url('${media.filePath}')` }"></div>
                <video v-else-if="isVideo(media.fileName)" class="absolute inset-0 w-full h-full object-cover" controls :poster=media.filePath>
                  <source :src="media.filePath" type="video/mp4">
                  您的浏览器不支持视频播放
                </video>
                <div v-else>
                  <a :href="media.filePath">{{ media.filePath+media.fileName }}</a>
                </div>

                &lt;!&ndash; 绝对定位的渐变遮罩层，初始透明，悬停时显示 &ndash;&gt;
                <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-end">
                  &lt;!&ndash; 底部内容容器，包含内边距并占满宽度 &ndash;&gt;
                  <div class="p-4 w-full">
                    &lt;!&ndash; 水平布局容器，两端对齐并垂直居中 &ndash;&gt;
                    <div class="flex justify-between items-center">
                      &lt;!&ndash; 媒体操作名称，白色文字，超出120px截断显示省略号 &ndash;&gt;
                      <span class="text-white text-sm font-medium truncate max-w-[120px]">{{ media.operation }}</span>
                      &lt;!&ndash; 操作按钮组，水平排列且间距为0.5rem &ndash;&gt;
                      <div class="flex space-x-2">
                        &lt;!&ndash; 预览按钮，白色图标，悬停时变为主题色 &ndash;&gt;
                        <button @click="previewMedia(media)"  title="预览">
                          <i class="fa fa-eye"></i>
                        </button>
                        &lt;!&ndash; 编辑按钮，白色图标，悬停时变为主题色 &ndash;&gt;
                        <button @click="editMedia(media)" title="编辑">
                          <i class="fa fa-pencil"></i>
                        </button>
                        &lt;!&ndash; 删除按钮，白色图标，悬停时变为红色 &ndash;&gt;
                        <button @click="deleteMedia(media)" title="删除">
                          <i class="fa fa-trash"></i>
                        </button>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="mt-2">
                <p class="text-sm font-medium text-gray-700 truncate">{{ media.fileName }}</p>
                <div class="flex justify-between items-center mt-1">
                  <p class="text-xs text-gray-500">{{ getFileSize(media.fileSize) || '未知大小' }}</p>
                  <span class="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded">
                    {{ formatDateTime(media.createTime || Date.now()) }}
                  </span>
                </div>
              </div>
            </div>-->
<!--            <div v-for="(media, index) in constructionMedia" :key="index" class="group relative rounded-lg overflow-hidden shadow-md h-64">
              &lt;!&ndash; 媒体内容：图片/视频 &ndash;&gt;
              <div v-if="isImage(media.fileName)" class="absolute inset-0 bg-center bg-contain bg-no-repeat" :style="{ backgroundImage: `url('${media.filePath}')` }"></div>
              <video v-else-if="isVideo(media.fileName)" class="absolute inset-0 w-full h-full object-cover" controls :poster=media.filePath>
                <source :src="media.filePath" type="video/mp4">
                您的浏览器不支持视频播放
              </video>
              <div v-else>
                <a :href="media.filePath">{{ media.filePath + media.fileName }}</a>
              </div>

              &lt;!&ndash; 悬停遮罩层（修正定位和悬停关联） &ndash;&gt;
              <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
                <div class="p-4 w-full">
                  <div class="flex justify-between items-center text-white">
                    &lt;!&ndash; 操作名称 &ndash;&gt;
                    <span class="text-sm font-medium truncate max-w-[120px]">{{ media.operation }}</span>
                    &lt;!&ndash; 操作按钮组（添加悬停颜色） &ndash;&gt;
                    <div class="flex space-x-2">
                      <button @click="previewMedia(media)" title="预览" class="hover:text-blue-500">
                        <i class="fa fa-eye"></i>
                      </button>
                      <button @click="editMedia(media)" title="编辑" class="hover:text-green-500">
                        <i class="fa fa-pencil"></i>
                      </button>
                      <button @click="deleteMedia(media)" title="删除" class="hover:text-red-500">
                        <i class="fa fa-trash "></i>
                      </button>
                    </div>
                  </div>
                </div>
              </div>

              &lt;!&ndash; 底部信息 &ndash;&gt;
              <div class="mt-2 bg-white p-4">
                <p class="text-sm font-medium text-gray-700 truncate">{{ media.fileName }}</p>
                <div class="flex justify-between items-center mt-1 text-xs text-gray-500">
                  <p>{{ getFileSize(media.fileSize) || '未知大小' }}</p>
                  <span class="bg-blue-100 text-blue-700 px-2 py-0.5 rounded">
        {{ formatDateTime(media.createTime || Date.now()) }}
      </span>
                </div>
              </div>
            </div>-->
            <div v-for="(media, index) in constructionMedia" :key="index" class="group relative rounded-lg overflow-hidden shadow-md h-64">
              <!-- 媒体内容（图片/视频） -->
              <div v-if="isImage(media.fileName)" class="absolute inset-0 bg-center bg-contain bg-no-repeat" :style="{ backgroundImage: `url('${media.filePath}')` }"></div>
              <video v-else-if="isVideo(media.fileName)" class="absolute inset-0 w-full h-full object-cover" controls :poster=media.filePath>
                <source :src="media.filePath" type="video/mp4">
              </video>
              <div v-else><a :href="media.filePath">{{ media.filePath + media.fileName }}</a></div>

              <!-- 遮罩层（添加 z-index 并确保层级正确） -->
              <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end z-20">
                <div class="p-4 w-full z-10"> <!-- 按钮容器层级高于遮罩层 -->
                  <div class="flex justify-between items-center text-white">
                    <!-- 操作名称（明确颜色和尺寸） -->
                    <span class="text-sm font-medium truncate max-w-[120px] text-white">
          {{ media.operation }}
        </span>
                    <!-- 按钮组（添加固定尺寸和颜色） -->
                    <div class="flex space-x-1">
                      <button @click="previewMedia(media)" title="预览" class=" flex-shrink-0 rounded=lg text-white hover:text-blue-500">
                        <i class="fa fa-eye">预览</i>
                      </button>
<!--                      <button @click="editMedia(media)" title="编辑" class=" flex-shrink-0 text-white hover:text-green-500">
                        <i class="fa fa-pencil">编辑</i>
                      </button>-->
                      <button @click="deleteMedia(media)" title="删除" class=" flex-shrink-0 rounded=lg text-white hover:text-red-500">
                        <i class="fa fa-trash">删除</i>
                      </button>
                    </div>
                  </div>
                </div>
              </div>

              <!-- 底部信息 -->
              <div class="mt-2 bg-white p-4">...</div>
            </div>
          </div>
        </div>

        <!-- 详细参数表格 -->
        <div class="bg-gray-50 rounded-lg p-4 mb-8">
          <h3 class="text-lg font-semibold mb-4 text-neutral">详细参数</h3>
          <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
            <div class="detail-row">
              <div>
                <p class="detail-label">桩号 {{ pile.pileNumber }}</p>
              </div>
              <div>
                <p class="detail-label">里程 K0+{{ pile.mileage }} m</p>
              </div>
              <div>
                <p class="detail-label">偏距  {{pile.offset<0 ? '左'+pile.offset*-1 : '右'+pile.offset}}m</p>
              </div>
              <div>
                <p class="detail-label">桩径 {{ pile.pileDiameter }} m</p>
              </div>
            </div>


            <div class="detail-row">
              <div>
                <p class="detail-label">坐  标X {{ pile.coordinateX }} m</p>
              </div>
              <div>
                <p class="detail-label">坐  标Y {{ pile.coordinateY }} m</p>
              </div>
              <div>
                <p class="detail-label">桩顶高程 {{ pile.pileTopElevation }} m</p>
              </div>
              <div>
                <p class="detail-label">桩底高程 {{ pile.pileBottomElevation }} m</p>
              </div>
            </div>


            <div class="detail-row">
              <div>
                <p class="detail-label"><span @dblclick="startEditing('elevationCasingPipe',pile.elevationCasingPipe,false)">护筒顶高程 {{ pile.elevationCasingPipe }} m</span></p>
              </div>
              <div>
              <p class="detail-label"><span @dblclick="startEditing('groundElevation',pile.groundElevation,false)">实测地面高程 {{ pile.groundElevation }} m</span></p>
              </div>
              <div>
                <p class="detail-label"><span @dblclick="startEditing('elevationBetweenRockAndSoil',pile.elevationBetweenRockAndSoil,false)">岩土交界高程 {{ pile.elevationBetweenRockAndSoil }} m</span></p>
              </div>
              <div>
                <p class="detail-label"><span @dblclick="startEditing('actualPileBottomElevation',pile.actualPileBottomElevation,false)">实际桩底高程 {{ pile.actualPileBottomElevation }} m</span></p>
              </div>
            </div>
            <div class="detail-row">

              <div>
                <p class="detail-label">桩身 长度 {{ pile.pileLength }} m</p>
              </div>

              <div>
                <p class="detail-label">钢筋笼长度 {{ pile.steelCageLength }} m</p>
              </div>

              <div>
                <p class="detail-label"><span @dblclick="startEditing('actualSteelCageLength',pile.actualSteelCageLength,false)">钢筋笼实际长度 {{ pile.actualSteelCageLength }} m</span></p>
              </div>
            </div>
            <div class="detail-row">
              <div>
                <p class="detail-label"><span @dblclick="startEditing('actualPouringVolume',pile.actualPouringVolume,false)">混凝土实际浇筑方量 {{ pile.actualPouringVolume }} m³</span></p>
              </div>
              <div>
                <p class="detail-label" >
                  <span @dblclick="startEditing('testBlockNumber',pile.testBlockNumber,false)">试压块编号 {{ pile.testBlockNumber }}</span>
                </p>

              </div>
              <div>
                <p class="detail-label"><span @dblclick="startEditing('weather',pile.weather,false)">浇筑天气 {{ pile.weather }} ℃</span></p>
              </div>
            </div>

          </div>
        </div>

      <!--   编辑框     -->
<!--        <div v-if="isEditOpen" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
          <div class="bg-white rounded-lg p-6 max-w-md w-full mx-4 transform transition-all">
            <div class="flex justify-between items-center mb-4">
              <el-date-picker
                  v-if="isTime"
                  v-model="editValue"
                  @keyup.enter="save"
                  @blur="save"
                  type="datetime"
              >
              </el-date-picker>
              <input v-else v-model="editValue"   @keyup.enter="save" @blur="save">
            </div>
            <div class="flex justify-between items-center mb-4">
              <button class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="cancel">
                <i class="fa fa-trash mr-1"></i>
                <span>取消</span>
              </button>
              <button class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="save">
                <i class="fa fa-trash mr-1"></i>
                <span>修改</span>
              </button>
            </div>
          </div>

        </div>-->

        <!--   编辑框     -->
        <div v-if="isEditOpen" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
          <div class="bg-white rounded-lg p-4 max-w-sm w-full mx-4 transform transition-all shadow-lg">
            <div class="flex justify-between items-center mb-3 border-b border-gray-200 pb-2">
              <el-date-picker
                  v-if="isTime"
                  v-model="editValue"
                  @keyup.enter="save"
                  @blur="save"
                  type="datetime"
                  placeholder="请选择日期时间"
                  class="w-full"
              >
              </el-date-picker>
              <input  v-else v-model="editValue"   @keyup.enter="save" @blur="save" placeholder="请输入内容" class="w-full border-none outline-none" />
            </div>
            <div class="flex justify-between items-center mb-3">
              <button class="bg-red-500 hover:bg-red-600 text-white px-3 py-1.5 rounded-lg transition-colors flex items-center space-x-1" @click="cancel">
                <i class="fa fa-trash mr-1"></i>
                <span>取消</span>
              </button>
              <button class="bg-green-500 hover:bg-green-600 text-white px-3 py-1.5 rounded-lg transition-colors flex items-center space-x-1" @click="save">
                <i class="fa fa-check mr-1"></i>
                <span>修改</span>
              </button>
            </div>
          </div>

        </div>

        <!-- 施工时间线 -->
        <div class="bg-white rounded-lg p-4">
          <h3 class="text-lg font-semibold mb-6 text-neutral">施工时间线</h3>
          <div class="timeline">
            <div class="timeline-item" v-for="(item, index) in constructionTimeline" :key="index">
              <div class="flex justify-between">
                <h4 class="font-medium">{{ item.name }}</h4>
<!--                <span class="text-sm text-gray-500">{{ item.time || '&#45;&#45;:&#45;&#45;:&#45;&#45;' }}</span>-->
                <span @dblclick="startEditing(item.key,item.time,true)">{{ item.time || '--:--:--' }}</span>
              </div>
              <p class="text-sm text-gray-600 mt-1">{{ item.description }}</p>
            </div>
          </div>
        </div>
      </div>

      <!-- 底部操作栏 -->
      <div class="flex justify-between items-center">
        <button class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="goBack">
          <i class="fa fa-arrow-left mr-1"></i>
          <span>返回列表</span>
        </button>
        <div class="flex space-x-3">
          <button class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="printPile">
            <i class="fa fa-print mr-1"></i>
            <span>打印</span>
          </button>
          <button class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition-colors flex items-center space-x-1" @click="deletePile">
            <i class="fa fa-trash mr-1"></i>
            <span>删除</span>
          </button>
        </div>
      </div>
    </main>

    <!-- 页脚 -->
    <footer class="mt-12 py-6 border-t border-gray-200">
      <div class="flex flex-col md:flex-row justify-between items-center">
        <p class="text-gray-500 text-sm">© 2025 桩基工程管理系统. 保留所有权利.</p>
        <div class="flex space-x-6 mt-4 md:mt-0">
          <a href="#" class="text-gray-500 hover:text-primary transition-colors">
            <i class="fa fa-question-circle mr-1"></i>帮助
          </a>
          <a href="#" class="text-gray-500 hover:text-primary transition-colors">
            <i class="fa fa-file-text mr-1"></i>文档
          </a>
          <a href="#" class="text-gray-500 hover:text-primary transition-colors">
            <i class="fa fa-cog mr-1"></i>设置
          </a>
        </div>
      </div>
    </footer>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import {createPouringTableAPI, putPileAPI, searchPileAPI} from "@/apis/api_pile.js";
import {deleteImageAPI, deleteInformationAPI, getPileImagesAPI, uploadPileImageAPI} from "@/apis/api_pile_image.js";
import { useRoute } from 'vue-router';
import router from "@/router/index.js";
import axios from "axios";
import {ElMessage} from "element-plus";
import {useUserStore} from "@/stores/userStore.js";
const { token } = useUserStore(); // 解构响应式令牌
const route = useRoute();



// 文件服务器配置
//const FILE_SERVER_URL = `${import.meta.env.VITE_APP_API_BASE_URL}/images/fileservice/`;
const FILE_SERVER_URL = `${import.meta.env.VITE_APP_API_BASE_URL}/images/fileservice/`;
const IMAGE_BASE_URL = `${FILE_SERVER_URL}`;

// 状态管理
const isLoading = ref(false);
const uploadProgress = ref(0);

// 桩基数据
const pile = ref({});
const imagesRes = ref({});
const pileNumber = ref('54-1');

// 施工影像资料
const constructionMedia = ref([]);
const excelFiles = ref([]);

// 上传状态
const isUploadModalOpen = ref(false);
const selectedOperation = ref('现场收方单');
const selectedFile = ref(null);
const fileInput = ref(null);

//数据是否完整
const isOver=ref(false);

// 页面加载时获取数据
onMounted(() => {
  getInfo();
});

const searchPileNumber=ref("");
const searchPile=()=>{
  try {
    // 假设 row.pileNumber 是具体数值（如 51-1），正确拼接 URL
    /*const targetUrl = `http://192.168.1.245:5173/pile/pileInfo/${searchPileNumber.value}`; // 示例：51-1

    // 页面跳转（使用 window.location.href）
    window.location.href = targetUrl;*/
    router.push(`/pile/pileInfo/${searchPileNumber.value}`);
    ElMessage.info(searchPileNumber.value)
  }catch (error){
    console.log(error);
  }
/*
  if (!searchPileNumber) {
    // 可以添加提示用户的逻辑
    return;
  }
  console.log(searchPileNumber);
  router.push(`/pile/pileInfo/${searchPileNumber.value}`);
*/

}


// 获取桩基信息和影像资料
const getInfo1 = async () => {
  isLoading.value = true;
  pileNumber.value = route.params.pileNumber;// 若路由为 /pileInfo/51-1，则值为 "51-1"
  console.log(route.params.pileNumber);

  try {
    // 获取桩基基本信息
    const pileRes = await searchPileAPI(pileNumber.value);
    pile.value = pileRes.data;

    // 获取桩基影像资料
    const res = await getPileImagesAPI(pileNumber.value);
    imagesRes.value=res.data
    console.log("获取桩基影像资料=========>",imagesRes);

    constructionMedia.value = imagesRes.data.map(media => ({
      ...media,
      // 确保所有文件路径都使用统一的服务器地址前缀
      filePath: media.filePath.startsWith('http')
          ? media.filePath
          : `${IMAGE_BASE_URL}${media.filePath}`
    }));

    const file=imagesRes.data.map(image => ({
      ...image,
    }))

    console.log(file);
  } catch (error) {
    console.error('获取数据失败:', error);
    //alert(`加载数据失败: ${error.message || '网络错误'}`);
  } finally {
    isLoading.value = false;
  }
};

const getInfo = async () => {

  // 清空数据
  pile.value={}
  constructionMedia.value = [];
  excelFiles.value =[];

  isLoading.value = true;
  pileNumber.value = route.params.pileNumber;
  console.log(route.params.pileNumber);

  try {
    const pileRes = await searchPileAPI(pileNumber.value);
    pile.value = pileRes.data;
    isOver.value = checkPileData(pile.value)
    const res = await getPileImagesAPI(pileNumber.value);
    imagesRes.value=res.data
    console.log(imagesRes.value);
    // 拆分数据
    const excelGroup = []; // Excel 文件组
    const otherGroup = []; // 其他类型组
    const targetFileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';

    imagesRes.value.forEach(item => {
      if (item.fileType === targetFileType) {
        excelGroup.push({
          ...item,
          filePath: item.filePath.startsWith('http')
              ? item.filePath
              : `${IMAGE_BASE_URL}${item.filePath}`
        });
      } else {
        otherGroup.push({
          ...item,
          filePath: item.filePath.startsWith('http')
              ? item.filePath
              : `${IMAGE_BASE_URL}${item.filePath}`
        });
      }
    });

    // 处理后的结果
    constructionMedia.value = otherGroup; // 其他类型（如图片）
    excelFiles.value = excelGroup; // Excel 文件单独分组

    console.log('Excel 组:', excelGroup);
    console.log('其他组:', otherGroup);

  } catch (error) {
    console.error('获取数据失败:', error);
  } finally {
    isLoading.value = false;
  }
};
const checkPileData=(pileData) =>{
  if (
      pileData.id === null ||
      pileData.id === undefined ||
      pileData.pileNumber === null ||
      pileData.pileNumber === "" ||
      pileData.mileage === null ||
      pileData.mileage === undefined ||
      pileData.offset === null ||
      pileData.offset === undefined ||
      pileData.coordinateX === null ||
      pileData.coordinateX === undefined ||
      pileData.coordinateY === null ||
      pileData.coordinateY === undefined ||
      pileData.pileBottomElevation === null ||
      pileData.pileBottomElevation === undefined ||
      pileData.pileTopElevation === null ||
      pileData.pileTopElevation === undefined ||
      pileData.pileDiameter === null ||
      pileData.pileDiameter === undefined ||
      pileData.pileLength === null ||
      pileData.pileLength === undefined ||
      pileData.steelCageLength === null ||
      pileData.steelCageLength === undefined ||
      pileData.overPouringLength === null ||
      pileData.overPouringLength === undefined ||
      pileData.groundElevation === null ||
      pileData.groundElevation === undefined ||
      pileData.actualPileBottomElevation === null ||
      pileData.actualPileBottomElevation === undefined ||
      pileData.holeOpeningTime === null ||
      pileData.holeOpeningTime === undefined ||
      pileData.holeCompletionTime === null ||
      pileData.holeCompletionTime === undefined ||
      pileData.reinforcementCageLoweringTime === null ||
      pileData.reinforcementCageLoweringTime === undefined ||
      pileData.pouringTime === null ||
      pileData.pouringTime === undefined ||
      pileData.testBlockNumber === null ||
      pileData.testBlockNumber === "" ||
      pileData.actualPouringVolume === null ||
      pileData.actualPouringVolume === undefined ||
      pileData.elevationBetweenRockAndSoil === null ||
      pileData.elevationBetweenRockAndSoil === undefined ||
      pileData.elevationCasingPipe === null ||
      pileData.elevationCasingPipe === undefined ||
      pileData.weather === null ||
      pileData.weather === "" ||
      pileData.actualSteelCageLength === null ||
      pileData.actualSteelCageLength === undefined ||
      pileData.timeForReinforcementCageAcceptance === null ||
      pileData.timeForReinforcementCageAcceptance === undefined ||
      pileData.timeForHoleFormationAcceptance === null ||
      pileData.timeForHoleFormationAcceptance === undefined
  ) {
    console.log("数据完整检查=========>",pileData.pileNumber+pileData.timeForHoleFormationAcceptance )
    return false;
  }
  return true;
}
// 处理文件上传
const handleFileUpload = (event) => {
  const file = event.target.files[0];
  if (file) {
    if (!isAllowedFileType(file)) {
      alert('仅支持 JPG, PNG, MP4 格式的文件');
      fileInput.value.value = ''; // 清空文件选择
      return;
    }
    selectedFile.value = file;
  }

};


// 确认上传文件
const confirmUpload = async () => {
  if (!selectedFile.value) {
    alert('请选择要上传的文件');
    return;
  }

  try {
    // 创建表单数据
    const formData = new FormData();
    formData.append('file', selectedFile.value);
    formData.append('userId', 1);
    formData.append('pileNumber', pile.value.pileNumber);
    formData.append('operation', selectedOperation.value);

    // 显示上传进度
    uploadProgress.value = 0;

    // 调用上传API
    const response = await uploadPileImageAPI(formData, (progressEvent) => {
      if (progressEvent.lengthComputable) {
        uploadProgress.value = Math.round((progressEvent.loaded / progressEvent.total) * 100);
      }
    });

    /*const response = await axios.post(
        '/file/upload', // 确认URL正确性
        formData,
        {
          headers: {
            'Content-Type': 'multipart/form-data' // 可选，Axios自动处理FormData时可能无需手动设置
          },
          // 进度监听通过onUploadProgress配置
          onUploadProgress: (progressEvent) => {
            if (progressEvent.lengthComputable) {
              uploadProgress.value = Math.round((progressEvent.loaded / progressEvent.total) * 100);
            }
          }
        }
    );*/
    console.log(response.flag)
    if (response.flag) {
      // 上传成功，将新文件添加到列表
      const newMedia = {
        id: response.data.id || Date.now(),
        userId: 1,
        filePath: `${IMAGE_BASE_URL}${response.data.filePath}`,
        fileName: selectedFile.value.name,
        pileNumber: pile.value.pileNumber,
        operation: selectedOperation.value,
        fileSize: selectedFile.value.size,
        fileType: isImage(selectedFile.value.name) ? 'image' : 'video',
        createTime: new Date().toISOString()
      };

      constructionMedia.value.unshift(newMedia); // 添加到列表开头
      closeUploadModal();
      ElMessage.info(response.data);
      await getInfo();
    } else {
      ElMessage.error(`上传失败: ${response.data || '未知错误'}`);
    }
  } catch (error) {
    console.error('上传错误:', error);
    ElMessage.error('上传过程中发生错误，请重试');
  } finally {
    uploadProgress.value = 0;
  }
};



// 检查文件类型是否允许
const isAllowedFileType = (file) => {
  const allowedExtensions = ['jpg', 'jpeg', 'png', 'mp4'];
  const fileExtension = file.name.split('.').pop().toLowerCase();
  return allowedExtensions.includes(fileExtension);
};

// 计算施工耗时
const constructionHours = computed(() => {
  if (!pile.value.holeOpeningTime || !pile.value.pouringTime) return '未知';

  const startTime = new Date(pile.value.holeOpeningTime);
  const endTime = new Date(pile.value.pouringTime);
  const duration = (endTime - startTime) / (1000 * 60 * 60);
  return Math.round(duration * 10) / 10; // 保留一位小数
});

// 格式化日期时间
const formatDateTime = (dateTime) => {
  if (!dateTime) return '未记录';

  const date = new Date(dateTime);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};

// 施工时间线数据
const constructionTimeline = computed(() => [
  {
    key: "holeOpeningTime",
    name: '开孔',
    time: pile.value.holeOpeningTime ? formatDateTime(pile.value.holeOpeningTime) : null,
    description: '桩孔开始施工，记录初始时间'
  },
  {
    key: "holeCompletionTime",
    name: '成孔',
    time: pile.value.holeCompletionTime ? formatDateTime(pile.value.holeCompletionTime) : null,
    description: '桩孔施工完成，达到设计深度和直径要求'
  },
  {
    key: "timeForHoleFormationAcceptance",
    name: '成孔验收时间',
    time: pile.value.timeForHoleFormationAcceptance ? formatDateTime(pile.value.timeForHoleFormationAcceptance) : null,
    description: '桩孔验收合格，符合设计深度和直径要求'
  },
  {
    key: "timeForReinforcementCageAcceptance",
    name: '钢筋笼验收时间',
    time: pile.value.timeForReinforcementCageAcceptance ? formatDateTime(pile.value.timeForReinforcementCageAcceptance) : null,
    description: '钢筋笼验收时间，符合设计长度和间距要求'
  },
  {
    key: "reinforcementCageLoweringTime",
    name: '下放钢筋笼',
    time: pile.value.reinforcementCageLoweringTime ? formatDateTime(pile.value.reinforcementCageLoweringTime) : null,
    description: '钢筋笼下放至孔内，位置准确固定牢固'
  },
  {
    key: "pouringTime",
    name: '浇筑混凝土',
    time: pile.value.pouringTime ? formatDateTime(pile.value.pouringTime) : null,
    description: '开始浇筑混凝土，完成桩基施工'
  }
]);

// 判断是否为图片
const isImage = (fileName) => {
  const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
  const fileExtension = fileName.split('.').pop().toLowerCase();
  return imageExtensions.includes(fileExtension);
};
// 判断是否为图片
const isVideo = (fileName) => {
  const imageExtensions = ['mp4', 'mp3', 'avi'];
  const fileExtension = fileName.split('.').pop().toLowerCase();
  return imageExtensions.includes(fileExtension);
};

// 获取文件大小
const getFileSize = (bytes) => {
  if (!bytes) return null;
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  if (bytes === 0) return '0 Bytes';
  const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${sizes[i]}`;
};

// 打开上传模态框
const openUploadModal = () => {
  isUploadModalOpen.value = true;
};

// 关闭上传模态框
const closeUploadModal = () => {
  isUploadModalOpen.value = false;
  selectedFile.value = null;
  fileInput.value.value = ''; // 清空文件选择
};

// 预览媒体
const previewMedia = (media) => {
  console.log('预览媒体:', media);
  // 可以实现全屏预览功能
  window.open(media.filePath, '_blank');
};

// 编辑媒体
const editMedia = (media) => {
  console.log('编辑媒体:', media);
  // 可以实现编辑功能
};

// 删除媒体
const deleteMedia = async (media) => {
  if (confirm(`确定要删除 "${media.fileName+media.id+media.userId}" 吗？此操作不可撤销。`)) {

    const res=await deleteImageAPI(media.id,media.userId);
    console.log(res)
    if (res.flag){
      ElMessage.info(res.data);
      await getInfo()
    }else{
      ElMessage.error(res.data);
    }

  }
};

// 模拟方法
const editPile = () => {
  console.log('编辑桩基信息');
  // 这里可以添加编辑逻辑
};

const exportPile = () => {
  console.log('导出桩基信息');
  // 这里可以添加导出逻辑
};

const goBack = () => {
  console.log('返回列表');
  // 这里可以添加返回逻辑
  router.back()
};

const printPile = () => {
  console.log('打印桩基信息');
  window.print();
};

const deletePile = async () => {
  if (confirm('此操作仅仅删除所有资料excel报表，基础数据不会改变')) {
    const userid=1;
    const res=await deleteInformationAPI(pileNumber.value,userid);
    console.log(res.data);
    await getInfo()
  }
};

const isTime=ref(false)
const isEditOpen=ref()
const editKey=ref()
const editValue=ref()
const startEditing=(key,value,ist)=>{

  isEditOpen.value=true;
  editKey.value=key;
  editValue.value= value
  isTime.value=ist;

}

const cancel=async ()=>{
  isEditOpen.value=false;

  // 保存要复制的值到临时变量，确保不会被后续操作清空
  const textToCopy = editValue.value;

  // 使用增强版复制函数
  const copySuccess = await enhancedCopyToClipboard(textToCopy);

  if (copySuccess) {
    showToast('复制成功！')
  } else {
    showToast('复制失败，请手动复制', 'error')
  }
}
//---------------------------------
const save = async () => {
  console.log(pile.value.testBlockNumber)
  pile.value[editKey.value] = editValue.value

  await putPileAPI(pile.value)
  isEditOpen.value = false;

/*
  // 保存要复制的值到临时变量，确保不会被后续操作清空
  const textToCopy = editValue.value;

  // 使用增强版复制函数
  const copySuccess = await enhancedCopyToClipboard(textToCopy);

  if (copySuccess) {
    showToast('复制成功！')
  } else {
    showToast('复制失败，请手动复制', 'error')
  }
*/

  editKey.value = ""
  editValue.value = "";
}

// 增强版复制函数，提供多种复制方式
const enhancedCopyToClipboard = async (text) => {
  try {
    // 方法1: 使用现代 Clipboard API (需要安全上下文)
    if (navigator.clipboard) {
      await navigator.clipboard.writeText(text);
      console.log('使用 Clipboard API 复制成功');
      return true;
    }

    // 方法2: 使用传统 textarea + execCommand 方法
    const textarea = document.createElement('textarea');
    textarea.value = text;

    // 防止在 iOS 上调整视图
    textarea.style.position = 'fixed';
    textarea.style.opacity = '0';

    document.body.appendChild(textarea);
    textarea.select();

    // 执行复制命令
    const result = document.execCommand('copy');
    document.body.removeChild(textarea);

    if (result) {
      console.log('使用 execCommand 复制成功');
      return true;
    }

    console.error('两种复制方法均失败');
    return false;

  } catch (error) {
    console.error('复制过程中出错:', error);
    return false;
  }
}

// 简单的提示框函数
const showToast = (message, type = 'success') => {
  // 这里可以实现一个自定义的提示框组件
  console.log(`${type.toUpperCase()}: ${message}`);
  // 实际项目中可以使用 Vue 组件显示提示
}

//---------------------------------


const error = ref('')
const loading = ref(false)

/*const exportExcel = async () => {
  if (loading.value) return

  loading.value = true
  error.value = ''

  try {
    /!*const response = await fetch(
        `${import.meta.env.VITE_APP_API_BASE_URL}:8083/pileData/createPouringTable?id=${pile.value.id}`,
        { method: 'GET' }
    )

    if (!response.ok) {
      throw new Error(`HTTP错误 ${response.status}`)
    }*!/

    const res = await createPouringTableAPI(pile.value.id)
    console.log("2025年6月4日20:39:13===========",res)
    if(res.flag){

      const url = `${import.meta.env.VITE_APP_API_BASE_URL}:9000/fileservice/${pileNumber.value}/${pileNumber.value}号桩基质检及收方资料.xlsx`;
      const a = document.createElement('a')
      a.href = url
      a.download = `${pileNumber.value}号桩基质检及收方资料.xlsx`
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      URL.revokeObjectURL(url)

      await getInfo()
    }



  } catch (err) {
    error.value = err.message || '导出失败'
    console.error('导出错误:', err)
  } finally {
    loading.value = false
  }
}*/

const exportExcel = async () => {
  if (loading.value) return

  loading.value = true
  error.value = ''

  try {
    const response = await fetch(
        `${import.meta.env.VITE_APP_API_BASE_URL}/apis/pileData/createPouringTable?id=${pile.value.id}`,
        { method: 'GET' ,headers: { 'authorization':'Bearer '+localStorage.getItem('access_token')} }
    )

    if (!response.ok) {
      throw new Error(`HTTP错误 ${response.status}`)
    }else {

      const url = `${import.meta.env.VITE_APP_API_BASE_URL}/images/fileservice/${pileNumber.value}/${pileNumber.value}号桩基质检及收方资料.xlsx`;
      const a = document.createElement('a')
      a.href = url
      a.download = `${pileNumber.value}号桩基质检及收方资料.xlsx`
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      URL.revokeObjectURL(url)

      await getInfo()
    }



  } catch (err) {
    error.value = err.message || '导出失败'
    console.error('导出错误:', err)
  } finally {
    loading.value = false
  }
}

// 在 onMounted 下方添加 watch 监听
onMounted(() => {
  getInfo(); // 初始加载数据
});

// 添加路由参数监听
watch(
    () => route.params.pileNumber, // 监听路由中的 pileNumber 参数
    (newId, oldId) => {
      if (newId !== oldId) { // 当参数变化时

        getInfo(); // 重新获取数据
      }
    },
    { immediate: true } // 组件初始化时立即执行（可选，根据需求）
);
</script>

<style scoped>
@layer utilities {
  .content-auto {
    content-visibility: auto;
  }
  .card-shadow {
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
  }
  .card-hover {
    transition: transform 0.3s ease, box-shadow 0.3s ease;
  }
  .card-hover:hover {
    transform: translateY(-5px);
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  }
  .stat-card {
    @apply bg-white rounded-xl p-4 card-shadow card-hover;
  }
  .detail-row {
    @apply grid grid-cols-1 md:grid-cols-2 gap-4 py-2 border-b border-gray-100;
  }
  .detail-label {
    @apply text-gray-500 font-medium;
  }
  .detail-value {
    @apply text-gray-800 font-semibold;
  }
  .timeline-item {
    @apply relative pl-8 pb-6;
  }
  .timeline-item::before {
    content: '';
    @apply absolute left-3 top-2 w-2 h-2 rounded-full bg-primary;
  }
  .timeline-item::after {
    content: '';
    @apply absolute left-3.5 top-4 w-0.5 h-full bg-gray-200;
  }
  .timeline-item:last-child::after {
    display: none;
  }
}
</style>
